//
// Created by ningjian on 2021/9/18.
//

#ifndef HOMO_TOOLS_HSCRIPT_ENGINE_HPP
#define HOMO_TOOLS_HSCRIPT_ENGINE_HPP

#include "nprime_and_rsquare.hpp"
#include "homo_block.h"
#include <functional>
#include <stdint.h>
#include <boost/smart_ptr.hpp>

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <memory>

using namespace  std;

/*
## 1. 输入设计

  定义计算表达式运作输入，采用类lisp风格，

  - 模乘   a1*b1 mod p  ,  a2*b2 mod p

    (!*  p  a1 b1  a2 b2)

  - 模幂   a1^e1 mod p   ,  a2^e2 mod p

    (!^  p  a1 e1  a2 e2)

  - 模乘之和   a1*b1 mod p  +  a2*b2 mod p

    (@*  p  a1 b1  a2 b2)

  - 模幂之积   a1^b1 mod p  **  a2^b2 mod p    *

    (@^  p  a1 e1  a2 e2)

## 2. 脚本功能设置

  - 设置p_bitcount    (set p_bitcount  0x400)

  - 设置e_bitcount    (set e_bitcount  0x400)

  - 保存输如文件    (saveblock test)
 */
class HScriptEngine {
public:
    HScriptEngine();
    int Eval(std::string script_text);

private:

    // 解析输入 拆分单个s表达式
    bool parse_expression_to_vector(std::string& script_text);
    // 解析单条表达式，并执行
    bool eval_expression(std::string & s_text);

    // set 命令
    bool eval_set(std::vector<std::string> &args);

    bool eval_save_block(std::vector<std::string> &args);

    bool eval_mod_mul(std::vector<std::string> &args);

    bool eval_mod_exp(std::vector<std::string> &args);

    bool eval_sum_mod_mul(std::vector<std::string> &args);

    bool eval_mul_mod_exp(std::vector<std::string> &args);

private:

    bool eval_mod_mul_and_exp(std::vector<std::string> &args, OP_CODE op);

    bool eval_sum_mul_mod_mul_and_exp(std::vector<std::string> &args, OP_CODE op);

    void save_vec_data(std::string filename, vector<uint8_t> &data);

    vector<uint8_t > calc_result_sum(boost::shared_array<uint8_t> p);

    vector<uint8_t > calc_result_mul(boost::shared_array<uint8_t> p);

    boost::shared_array<uint8_t>  hex_2_array(std::string hex, int array_size);

    vector<uint8_t > array_2_vector(boost::shared_array<uint8_t> arr, int arr_len);

    PBitCount get_pbc(int bitcount);
    EBitCount get_ebc(int bitcount);

    uint8_t  get_frame_id(int frame_index);

    std::vector<uint8_t> convert_result_number(std::vector<uint8_t> data);
    std::vector<uint8_t> convert_shared_array(boost::shared_array<uint8_t>, int length);

private:
    // 变量保存
    std::map<string,string> s_variable;
    // 单条表达式存储
    std::vector<std::string> s_expression;

    std::map<std::string, std::function<bool(std::vector<std::string> &)>> s_eval_fun;

    std::vector<HomoBlock> s_blocks;

    std::vector<boost::shared_array<uint8_t>> s_result;

    CAL_MODE last_cal_mode;

    std::vector<HomoFrame> s_frames;
};



template <typename ElemT>
struct HexTo {
    ElemT value;
    operator ElemT() const {return value;}
    friend std::istream& operator>>(std::istream& in, HexTo& out) {
        in >> std::hex >> out.value;
        return in;
    }
};

#endif //HOMO_TOOLS_HSCRIPT_ENGINE_HPP
